/*
    实现异步日志缓冲区
*/
#ifndef __M_BUF_H__
#define __M_BUF_H__

#include "util.hpp"
#include <vector>
#include <cassert>

namespace log_sys{
    #define DEFAULTBUFFERSIZE (1 * 1024 * 1024)
    #define THREASHOLDBUFFERSIZE (8 * 1024 * 1024)
    #define INCREMENTBUFFERSIZE (1 * 1024 * 1024 )

    class Buffer{
    public:
        Buffer()
            :_buffer(DEFAULTBUFFERSIZE)
            ,_readeridx(0) 
            ,_writeridx(0)
        {}

        // 向缓冲区放入字符串
        void push(const char* data, int len)
        {
            // 空间不够则扩容            
            ensureEnoughSize(len);

            // 调用copy将数据拷贝进缓冲区
            std::copy(data, data + len, &_buffer[_writeridx]);

            // 将当前写位置后移 
            mvWriter(len);
        }

        const char* begin()
        {
            return &_buffer[_readeridx];
        }

        int readablesize()
        {
            return (_writeridx - _readeridx);
        }

        int writeablesize()
        {
            return (_buffer.size() - _writeridx);
        }

        void mvReader(int len)
        {
            assert(len <= readablesize());
            _readeridx += len;
        }
        void reset()
        {
            _readeridx = 0;
            _writeridx = 0;

        } 

        void swap(Buffer& buffer)
        {
            // 这里直接调用vector内部实现的swap进行交换
            // 因为vector内部实现的swap 不涉及数据的移动，只有指针的交换
            // (提示vector的成员: _start, _finish, _endofstorage)
            _buffer.swap(buffer._buffer);
            std::swap(_readeridx, buffer._readeridx);
            std::swap(_writeridx, buffer._writeridx);
        }

        bool empty()
        {
            return (_writeridx == _readeridx);
        }
    
    private:
        void ensureEnoughSize(int len)
        {
            if (len <= writeablesize())
            {
                return;
            }
            int newsize = 0;
            if (_buffer.size() < THREASHOLDBUFFERSIZE)
            {
                newsize = _buffer.size() * 2 + len;
            }
            else
            {
                newsize = _buffer.size() + INCREMENTBUFFERSIZE + len;
            }
            _buffer.resize(newsize);
        }

        void mvWriter(int len)
        {
            assert(len + _writeridx <= _buffer.size());
            _writeridx += len;
        }

    private:
        std::vector<char> _buffer;
        int _readeridx; // 当前可读数据的指针
        int _writeridx; // 当前可写数据的指针
    };
}

#endif
